import {
  createEffect,
  createMemo,
  createSignal,
  mergeProps,
  on,
  splitProps,
  type JSXElement,
} from "solid-js";
import type { TooltipProps } from "./types";
import { Dynamic, render } from "solid-js/web";
import { Tooltip } from "bootstrap";
import type { HtmlElementOrComponent } from "@lib/types";
import type { JSX } from "solid-js/jsx-runtime";

const transformSolidTitle = (
  el: JSXElement
): Partial<Pick<Tooltip.Options, "html" | "title">> => {
  if (!el) {
    return {};
  }

  if (typeof el === "function") {
    return {
      title: () => {
        if (!this) {
          return "";
        }

        render(el, this!);
        return this! as Element;
      },
      html: true,
    };
  }

  if (el instanceof HTMLElement) {
    return {
      title: el.innerHTML,
      html: true,
    };
  }

  return {
    title: el as any,
  };
};

const SolidTooltip = <T extends HtmlElementOrComponent = "span">(
  p: TooltipProps<T>
) => {
  const [local, props] = splitProps(mergeProps({ as: "span" }, p), [
    "onRef",
    "as",
    "options",
    "children",
    "title",
  ]);

  const [ref, setRef] = createSignal<HTMLElement | undefined>(undefined);
  const mergedOptions = createMemo(() => {
    return {
      ...local.options,
      ...transformSolidTitle(local.title)
    }
  })

  const tooltip = createMemo(() => {
    const el = ref();

    if (el) {
      const options = mergedOptions();
      return new Tooltip(el, options); // html 原始属性title
    }

    return undefined;
  });

  createEffect(
    on(tooltip, (instance) => {
      local.onRef?.(instance);
    })
  );

  const dynamicProps = createMemo(() => {
    const dyn: JSX.HTMLAttributes<any> = {};
    if (local.as === undefined) {
      dyn.tabIndex = 0;
    }

    return dyn;
  });

  return (
    <Dynamic
      component={local.as}
      {...props}
      ref={setRef}
      data-bs-toggle="tooltip"
      {...(dynamicProps() as any)}
    >
      {local.children}
    </Dynamic>
  );
};

export default SolidTooltip;
